home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / misc / pdflib / p_jpeg.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  10KB  |  379 lines

  1. /* p_jpeg.c
  2.  * Copyright (C) 1997-98 Thomas Merz. All rights reserved.
  3.  *
  4.  * JPEG processing for PDFlib
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. #ifdef POSIX
  11. #include <unistd.h>
  12. #endif
  13.  
  14. #include "p_intern.h"
  15.  
  16. /* 
  17.  * The following enum is stolen from the IJG JPEG library
  18.  * Comments added by tm.
  19.  * This table contains far too many names since pdflib
  20.  * is rather simple-minded about markers.
  21.  */
  22.  
  23. typedef enum {        /* JPEG marker codes            */
  24.   M_SOF0  = 0xc0,    /* baseline DCT                */
  25.   M_SOF1  = 0xc1,    /* extended sequential DCT        */
  26.   M_SOF2  = 0xc2,    /* progressive DCT            */
  27.   M_SOF3  = 0xc3,    /* lossless (sequential)        */
  28.   
  29.   M_SOF5  = 0xc5,    /* differential sequential DCT        */
  30.   M_SOF6  = 0xc6,    /* differential progressive DCT        */
  31.   M_SOF7  = 0xc7,    /* differential lossless        */
  32.   
  33.   M_JPG   = 0xc8,    /* JPEG extensions            */
  34.   M_SOF9  = 0xc9,    /* extended sequential DCT        */
  35.   M_SOF10 = 0xca,    /* progressive DCT            */
  36.   M_SOF11 = 0xcb,    /* lossless (sequential)        */
  37.   
  38.   M_SOF13 = 0xcd,    /* differential sequential DCT        */
  39.   M_SOF14 = 0xce,    /* differential progressive DCT        */
  40.   M_SOF15 = 0xcf,    /* differential lossless        */
  41.   
  42.   M_DHT   = 0xc4,    /* define Huffman tables        */
  43.   
  44.   M_DAC   = 0xcc,    /* define arithmetic conditioning table    */
  45.   
  46.   M_RST0  = 0xd0,    /* restart                */
  47.   M_RST1  = 0xd1,    /* restart                */
  48.   M_RST2  = 0xd2,    /* restart                */
  49.   M_RST3  = 0xd3,    /* restart                */
  50.   M_RST4  = 0xd4,    /* restart                */
  51.   M_RST5  = 0xd5,    /* restart                */
  52.   M_RST6  = 0xd6,    /* restart                */
  53.   M_RST7  = 0xd7,    /* restart                */
  54.   
  55.   M_SOI   = 0xd8,    /* start of image            */
  56.   M_EOI   = 0xd9,    /* end of image                */
  57.   M_SOS   = 0xda,    /* start of scan            */
  58.   M_DQT   = 0xdb,    /* define quantization tables        */
  59.   M_DNL   = 0xdc,    /* define number of lines        */
  60.   M_DRI   = 0xdd,    /* define restart interval        */
  61.   M_DHP   = 0xde,    /* define hierarchical progression    */
  62.   M_EXP   = 0xdf,    /* expand reference image(s)        */
  63.   
  64.   M_APP0  = 0xe0,    /* application marker, used for JFIF    */
  65.   M_APP1  = 0xe1,    /* application marker            */
  66.   M_APP2  = 0xe2,    /* application marker            */
  67.   M_APP3  = 0xe3,    /* application marker            */
  68.   M_APP4  = 0xe4,    /* application marker            */
  69.   M_APP5  = 0xe5,    /* application marker            */
  70.   M_APP6  = 0xe6,    /* application marker            */
  71.   M_APP7  = 0xe7,    /* application marker            */
  72.   M_APP8  = 0xe8,    /* application marker            */
  73.   M_APP9  = 0xe9,    /* application marker            */
  74.   M_APP10 = 0xea,    /* application marker            */
  75.   M_APP11 = 0xeb,    /* application marker            */
  76.   M_APP12 = 0xec,    /* application marker            */
  77.   M_APP13 = 0xed,    /* application marker            */
  78.   M_APP14 = 0xee,    /* application marker, used by Adobe    */
  79.   M_APP15 = 0xef,    /* application marker            */
  80.   
  81.   M_JPG0  = 0xf0,    /* reserved for JPEG extensions        */
  82.   M_JPG13 = 0xfd,    /* reserved for JPEG extensions        */
  83.   M_COM   = 0xfe,    /* comment                */
  84.   
  85.   M_TEM   = 0x01,    /* temporary use            */
  86.  
  87.   M_ERROR = 0x100    /* dummy marker, internal use only    */
  88. } JPEG_MARKER;
  89.  
  90. #define JPEG_BUFSIZE    512
  91.  
  92. static void
  93. pdf_data_source_JPEG_init(PDF *p, PDF_data_source *src)
  94. {
  95.   PDF_image    *image;
  96.  
  97.   image = (PDF_image *) src->private_data;
  98.  
  99.   src->buffer_start = PDF_malloc(JPEG_BUFSIZE, "PDF_data_source_JPEG_init");
  100.   src->buffer_length = JPEG_BUFSIZE;
  101.  
  102.   fseek(image->fp, image->startpos, SEEK_SET);
  103. }
  104.  
  105. static bool
  106. pdf_data_source_JPEG_fill(PDF *p, PDF_data_source *src)
  107. {
  108.   PDF_image    *image;
  109.  
  110.   image = (PDF_image *) src->private_data;
  111.  
  112.   src->next_byte = src->buffer_start;
  113.   src->bytes_available = fread(src->buffer_start, 1, JPEG_BUFSIZE, image->fp);
  114.  
  115.   if (src->bytes_available == 0)
  116.     return false;
  117.   else
  118.     return true;
  119. }
  120.  
  121. static void
  122. pdf_data_source_JPEG_terminate(PDF *p, PDF_data_source *src)
  123. {
  124.   PDF_image    *image;
  125.  
  126.   image = (PDF_image *) src->private_data;
  127.  
  128.   PDF_free((void *) src->buffer_start);
  129. }
  130.  
  131. /* read two byte parameter, MSB first */
  132. #define get_2bytes(fp) ((unsigned int) (getc(fp) << 8) + getc(fp))
  133.  
  134. static int 
  135. pdf_next_jpeg_marker(FILE *fp)
  136. { /* look for next JPEG Marker  */
  137.   int c, nbytes = 0;
  138.  
  139.   if (feof(fp))
  140.     return M_ERROR;                 /* dummy marker               */
  141.  
  142.   do {
  143.     do {                            /* skip to FF           */
  144.       nbytes++;
  145.       c = getc(fp);
  146.     } while (c != 0xFF);
  147.     do {                            /* skip repeated FFs        */
  148.       c = getc(fp);
  149.     } while (c == 0xFF);
  150.   } while (c == 0);                 /* repeat if FF/00                 */
  151.  
  152.   return c;
  153. }
  154.  
  155. /* open JPEG image and analyze marker */
  156. PDF_image *
  157. PDF_open_JPEG(PDF *p, char *filename)
  158. {
  159.   int b, c, unit;
  160.   unsigned long i, length;
  161. #define APP_MAX 255
  162.   unsigned char appstring[APP_MAX];
  163.   bool SOF_done = false;
  164.     PDF_image *image;
  165.  
  166.     image = (PDF_image *) PDF_malloc(sizeof(PDF_image), "PDF_open_JPEG");
  167.  
  168.     if (image == NULL)
  169.     return NULL;
  170.  
  171.     if ((image->fp = fopen(filename, READMODE)) == NULL) {
  172.     pdf_error(p, PDF_WARN, "Couldn't open JPEG file %s\n", filename);
  173.     PDF_free(image);
  174.     return NULL;
  175.     }
  176.  
  177.     image->filename    = filename;
  178.     image->closefunc    = PDF_close_JPEG;
  179.     image->compression    = dct;
  180.     image->adobe    = false;
  181.     image->dpi        = 0.0;
  182.     image->indexed        = false;
  183.  
  184.     image->src.init        = pdf_data_source_JPEG_init;
  185.     image->src.fill        = pdf_data_source_JPEG_fill;
  186.     image->src.terminate    = pdf_data_source_JPEG_terminate;
  187.     image->src.private_data    = (void *) image;
  188.  
  189.  
  190.   /* Tommy's special trick for Macintosh JPEGs: simply skip some  */
  191.   /* hundred bytes at the beginning of the file!          */
  192.   do {
  193.     do {                            /* skip if not FF           */
  194.       c = getc(image->fp);
  195.     } while (!feof(image->fp) && c != 0xFF);
  196.  
  197.     do {                            /* skip repeated FFs       */
  198.       c = getc(image->fp);
  199.     } while (c == 0xFF);
  200.  
  201.     /* remember start position */
  202.     if ((image->startpos = ftell(image->fp)) < 0L) {
  203.     PDF_free(image);
  204.     return NULL;
  205.     }
  206.  
  207.     image->startpos -= 2;           /* subtract marker length     */
  208.  
  209.     if (c == M_SOI) {
  210.       fseek(image->fp, image->startpos, SEEK_SET);
  211.       break;
  212.     }
  213.   } while (!feof(image->fp));
  214.  
  215. #define BOGUS_LENGTH    768
  216.   /* Heuristics: if we are that far from the start chances are
  217.    * it is a TIFF file with embedded JPEG data which we cannot
  218.    * handle - regard as hopeless...
  219.    */
  220.   if (feof(image->fp) || image->startpos > BOGUS_LENGTH) {
  221.     PDF_free(image);
  222.     return NULL;
  223.   }
  224.  
  225.   /* process JPEG markers */
  226.   while (!SOF_done && (c = pdf_next_jpeg_marker(image->fp)) != M_EOI) {
  227.     switch (c) {
  228.       case M_ERROR:
  229.     PDF_free(image);
  230.     return NULL;
  231.  
  232.       /* The following are not supported in PDF */
  233.       case M_SOF2:
  234.       case M_SOF3:
  235.       case M_SOF5:
  236.       case M_SOF6:
  237.       case M_SOF7:
  238.       case M_SOF9:
  239.       case M_SOF10:
  240.       case M_SOF11:
  241.       case M_SOF13:
  242.       case M_SOF14:
  243.       case M_SOF15:
  244.     PDF_free(image);
  245.     return NULL;
  246.  
  247.       case M_SOF0:
  248.       case M_SOF1:
  249.     length = get_2bytes(image->fp);    /* read segment length  */
  250.  
  251.     image->bpc         = getc(image->fp);
  252.     image->height            = get_2bytes(image->fp);
  253.     image->width             = get_2bytes(image->fp);
  254.     image->components        = getc(image->fp);
  255.  
  256.     SOF_done = true;
  257.     break;
  258.  
  259.       case M_APP0:        /* check for JFIF marker with resolution */
  260.     length = get_2bytes(image->fp);
  261.  
  262.     for (i = 0; i < length-2; i++) {    /* get contents of marker */
  263.       b = getc(image->fp);
  264.       if (i < APP_MAX)            /* store marker in appstring */
  265.         appstring[i] = b;
  266.     }
  267.  
  268.     /* Check for JFIF application marker and read density values
  269.      * per JFIF spec version 1.02.
  270.      * We only check X resolution, assuming X and Y resolution are equal.
  271.      * Use values only if resolution not preset by user or to be ignored.
  272.      */
  273.  
  274. #define ASPECT_RATIO    0    /* JFIF unit byte: aspect ratio only */
  275. #define DOTS_PER_INCH    1    /* JFIF unit byte: dots per inch     */
  276. #define DOTS_PER_CM    2    /* JFIF unit byte: dots per cm       */
  277.  
  278.     if (length >= 14 && !strncmp("JFIF", (char *) appstring, 4)) {
  279.       unit = appstring[7];                /* resolution unit */
  280.                           /* resolution value */
  281.       image->dpi = (appstring[8]<<8) + appstring[9];    
  282.  
  283.       if (image->dpi == 0.0)
  284.         break;
  285.  
  286.       switch (unit) {
  287.         /* tell the caller we didn't find a resolution value */
  288.         case ASPECT_RATIO:
  289.           image->dpi = 0.0;
  290.           break;
  291.  
  292.         case DOTS_PER_INCH:
  293.           break;
  294.  
  295.         case DOTS_PER_CM:
  296.           image->dpi *= 2.54;
  297.           break;
  298.  
  299.         default:                /* unknown ==> ignore */
  300.           image->dpi = 0.0;
  301.           break;
  302.       }
  303.     }
  304.         break;
  305.  
  306.       case M_APP14:                /* check for Adobe marker */
  307.     length = get_2bytes(image->fp);
  308.  
  309.     for (i = 0; i < length-2; i++) {    /* get contents of marker */
  310.       b = getc(image->fp);
  311.       if (i < APP_MAX)            /* store marker in appstring */
  312.         appstring[i] = b;
  313.     }
  314.  
  315.     /* Check for Adobe application marker. It is known (per Adobe's TN5116)
  316.      * to contain the string "Adobe" at the start of the APP14 marker.
  317.      */
  318.     if (length >= 12 && !strncmp("Adobe", (char *) appstring, 5))
  319.       image->adobe = true;            /* set Adobe flag */
  320.  
  321.     break;
  322.  
  323.       case M_SOI:        /* ignore markers without parameters */
  324.       case M_EOI:
  325.       case M_TEM:
  326.       case M_RST0:
  327.       case M_RST1:
  328.       case M_RST2:
  329.       case M_RST3:
  330.       case M_RST4:
  331.       case M_RST5:
  332.       case M_RST6:
  333.       case M_RST7:
  334.     break;
  335.  
  336.       default:            /* skip variable length markers */
  337.     length = get_2bytes(image->fp);
  338.     for (length -= 2; length > 0; length--)
  339.       (void) getc(image->fp);
  340.     break;
  341.     }
  342.   }
  343.  
  344.   /* do some sanity checks with the parameters */
  345.   if (image->height <= 0 || image->width <= 0 || image->components <= 0) {
  346.     PDF_free(image);
  347.     return NULL;
  348.   }
  349.  
  350.   if (image->bpc != 8) {
  351.     PDF_free(image);
  352.     return NULL;
  353.   }
  354.  
  355.   switch(image->components) {
  356.     case 1:
  357.     image->colorspace = DeviceGray;
  358.     break;
  359.     case 3:
  360.     image->colorspace = DeviceRGB;
  361.     break;
  362.     case 4:
  363.     image->colorspace = DeviceCMYK;
  364.     break;
  365.     default:
  366.     PDF_free(image);
  367.     return NULL;
  368.   }
  369.  
  370.   return image;
  371. }
  372.  
  373. void
  374. PDF_close_JPEG(PDF *p, PDF_image *image)
  375. {
  376.     fclose(image->fp);
  377.     PDF_free(image);
  378. }
  379.